package com.yhhvip.lottery.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yhhvip.exception.BusinessException;
import com.yhhvip.lottery.dao.mybatis.mapper.LotActivityMapper;
import com.yhhvip.lottery.dao.mybatis.mapper.LotActivityParticipantsMapper;
import com.yhhvip.lottery.dao.mybatis.mapper.LotPrizeMapper;
import com.yhhvip.lottery.dao.mybatis.mapper.LotUserMapper;
import com.yhhvip.lottery.dao.mybatis.model.*;
import com.yhhvip.lottery.domain.*;
import com.yhhvip.lottery.domain.res.ResActivityBaseVo;
import com.yhhvip.lottery.domain.res.ResActivityInfoVo;
import com.yhhvip.lottery.domain.res.ResWonInfoVo;
import com.yhhvip.lottery.service.LotActivityService;
import com.yhhvip.utils.DateUtils;
import com.yhhvip.utils.IdWorker;
import com.yhhvip.utils.JsonResult;
import com.yhhvip.utils.RandomUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author XOu
 * @version 1.0
 * @description 抽检活动业务处理层
 * @date 2018/6/18
 */
@Service
@Slf4j
@Transactional
public class LotActivityServiceImpl implements LotActivityService {

    @Autowired
    private LotActivityMapper activityMapper;

    @Autowired
    private LotActivityParticipantsMapper activityParticipantsMapper;

    @Autowired
    private LotUserMapper userMapper;

    @Autowired
    private LotPrizeMapper prizeMapper;

    @Override

    public ResActivityInfoVo getActivityById(Long activityId, Long userId) {
        //获取活动相关信息,包括奖品信息
        ResActivityInfoVo activityInfoVo = activityMapper.getActivityInfoByActivityId(activityId);
        if (null == activityInfoVo) {
            return null;
        }
        if (activityInfoVo.getCreateById().equals(userId)) {
            //查询收货完善信息
            Integer count = activityMapper.getJoinInfo(activityId);
            activityInfoVo.setUserAddressCount(count);
            //查询中奖路数
            Integer wonCount = activityMapper.getWonCount(activityId);
            activityInfoVo.setWonCount(wonCount);
        } else {
            activityInfoVo.setJoinPwd(null);
        }
        //查询是否已中奖和是否加入
        Integer isWon = activityMapper.findIsWonAndIsJoin(activityId, userId);
        int isJoin = 0;
        if (null != isWon) {
            isJoin = 1;
        }
        activityInfoVo.setIsJoin(isJoin);
        activityInfoVo.setIsWon(isWon);
        return activityInfoVo;
    }

    @Override
    public JsonResult draw(DrawVo drawVo) {
        Long activityId = drawVo.getActivityId();
        Long userId = drawVo.getUserId();
        LotActivity lotActivity = activityMapper.selectByPrimaryKey(activityId);
        if (null == lotActivity) {
            log.error("==========活动不存在");
            return JsonResult.build("活动不存在");
        }
        Byte ruleType = lotActivity.getRuleType();
        if (1 == drawVo.getIsManually()) {
            if (3 != ruleType) {
                log.error("==========非手动开奖,开奖失败");
                throw new BusinessException("非手动开奖,开奖失败");
            }
        }
        LotUser lotUser = userMapper.selectByPrimaryKey(userId);
        //开奖前对开奖信息做判断
        JsonResult jsonResult = preCheckout(lotActivity, lotUser);
        if (200 != jsonResult.getStatus()) {
            return jsonResult;
        }
        //获取到本次活动的所有奖品
        LotPrizeExample prizeExample = new LotPrizeExample();
        prizeExample.createCriteria().andActivityIdEqualTo(activityId);
        //获取到的奖品等级从大到小排序
        prizeExample.setOrderByClause("level desc");
        List<LotPrize> prizeList = prizeMapper.selectByExample(prizeExample);
        //获取本次活动的所有参与人员
        LotActivityParticipantsExample participantsExample = new LotActivityParticipantsExample();
        participantsExample.createCriteria().andActivityIdEqualTo(activityId);
        List<LotActivityParticipants> participantList = activityParticipantsMapper.selectByExample(participantsExample);
        //中奖名单
        List<LotActivityParticipants> wons;
        //随机数
        int random;
        //开奖实现
        if (null != prizeList && prizeList.size() > 0) {
            //遍历每一个奖品
            for (LotPrize lotPrize : prizeList) {
                if (participantList.size() < 1) {
                    break;
                }
                //奖品数量
                Integer prizeCount = lotPrize.getCount();
                //奖品类型 1:实物 2:优惠券
                Byte type = lotPrize.getType();
                //奖品id
                Long prizeId = lotPrize.getId();
                //判断奖品数量是否大于参与人数,及所有人都中了该奖
                if (participantList.size() <= prizeCount) {
                    wons = participantList;
                    updateByWon(wons, prizeId, type);
                    participantList.clear();
                    break;
                }
                //随机得到起始下标
                int i = participantList.size() - prizeCount;
                random = RandomUtils.getRandomByNumber(i);
                wons = new ArrayList<>();
                for (int j = 0; j < prizeCount; j++) {
                    wons.add(participantList.get(random));
                    participantList.remove(random);
                }
                updateByWon(wons, prizeId, type);
            }
        }
        if (participantList.size() > 0) {
            //其他人为未中奖状态
            updateByNotWon(participantList);
        }
        lotActivity.setStatus((byte) 2);
        lotActivity.setDrawTime(new Date());
        activityMapper.updateByPrimaryKeySelective(lotActivity);
        return JsonResult.ok();
    }

    @Override
    public PageInfo<ResActivityBaseVo> selectActivitys(ActivityQueryVo activityQueryVo) {
        PageHelper.startPage(activityQueryVo.getPageNum(), activityQueryVo.getPageSize());
        List<ResActivityBaseVo> activityList = activityMapper.selectActivitys(activityQueryVo);
        PageInfo<ResActivityBaseVo> ActivityInfo = new PageInfo<>(activityList);
        return ActivityInfo;
    }

    @Override
    public Long add(ActivityVo activityVo) {
        //先添加活动信息
        LotActivity activity = new LotActivity();
        Date currentDate = new Date();
        activity.setCreateTime(currentDate);
        BeanUtils.copyProperties(activityVo, activity);
        activity.setStatus((byte) 1);
        Byte ruleType = activityVo.getRuleType();
        List<PrizeVo> prizeVos = activityVo.getPrizes();

        PrizeVo vo = prizeVos.get(0);
        String prizeName = vo.getPrizeName();
        if (prizeVos.size() > 1) {
            prizeName = prizeName.concat(" 等");
        }
        activity.setDescription(prizeName);
        if (3 == ruleType) {
            activity.setEndTime(DateUtils.addDays(currentDate, 3));
        } else if (2 == ruleType) {
            activity.setSetLotteryTime(DateUtils.addDays(currentDate, 3));
        }
        int i = activityMapper.insertSelective(activity);
        if (1 != i) {
            return null;
        }
        //活动奖品处理
        LotPrize prize;
        for (PrizeVo prizeVo : prizeVos) {
            prize = new LotPrize();
            prize.setCreateTime(currentDate);
            prize.setActivityId(activity.getId());
            BeanUtils.copyProperties(prizeVo, prize);
            int j = prizeMapper.insertSelective(prize);
            if (1 != j) {
                throw new BusinessException("添加奖品失败");
            }
        }

        //更新活动发起人的次数
        Long createById = activityVo.getCreateById();
        LotUser user = userMapper.selectByPrimaryKey(createById);
        if (null == user) {
            throw new BusinessException("活动发起人用户信息为空");
        }
        user.setSponsorCount(user.getSponsorCount() + 1);
        userMapper.updateByPrimaryKeySelective(user);
        return activity.getId();
    }

    @Override
    public PageInfo<ResWonInfoVo> searchWonInfo(ReqWonInfoVo reqWonInfoVo) {
        PageHelper.startPage(reqWonInfoVo.getPageNum(), reqWonInfoVo.getPageSize());
        List<ResWonInfoVo> resWonInfoVos = activityParticipantsMapper.searchWonInfo(reqWonInfoVo);
        PageInfo<ResWonInfoVo> resWonInfoVoPageInfo = new PageInfo<>(resWonInfoVos);
        return resWonInfoVoPageInfo;
    }

    @Override
    public JsonResult joinLottery(ReqJoinLottery reqJoinLottery) {
        Long activityId = reqJoinLottery.getActivityId();
        Long userId = reqJoinLottery.getUserId();
        String reqJoinPwd = reqJoinLottery.getJoinPwd();
        Date currentDate = new Date();
        LotUserExample userExample = new LotUserExample();
        userExample.createCriteria().andIdEqualTo(userId).andStatusEqualTo((byte) 1).andTypeEqualTo((byte) 1);
        List<LotUser> users = userMapper.selectByExample(userExample);
        if (null == users || users.size() < 1) {
            return JsonResult.build("用户不存在或已被禁用!");
        }
        LotUser user = users.get(0);

        LotActivityExample activityExample = new LotActivityExample();
        activityExample.createCriteria().andIdEqualTo(activityId).andStatusEqualTo((byte) 1).andPutStatusEqualTo((byte) 1);
        List<LotActivity> lotActivitys = activityMapper.selectByExample(activityExample);
        if (null == lotActivitys || lotActivitys.size() < 1) {
            return JsonResult.build("活动不存在或不是未开奖状态!");
        }
        LotActivity activity = lotActivitys.get(0);

        //对规则做处理
        String joinPwd = activity.getJoinPwd();
        if (StringUtils.isNotBlank(joinPwd)) {
            if (!joinPwd.equals(reqJoinPwd)) {
                return JsonResult.build("参与口令错误!");
            }
        }
        Integer joinLimit = activity.getJoinLimit();
        Integer userCount = user.getLotteryCount();
        if (null != joinLimit) {
            if (userCount < joinLimit) {
                return JsonResult.build("参与次数未达到要求!");
            }
        }

        //判断是否已参加了该活动
        LotActivityParticipantsExample activityParticipantsExample = new LotActivityParticipantsExample();
        activityParticipantsExample.createCriteria().andUserIdEqualTo(userId).andActivityIdEqualTo(activityId);
        List<LotActivityParticipants> activityParticipants = activityParticipantsMapper.selectByExample(activityParticipantsExample);
        if (activityParticipants != null && activityParticipants.size() > 0) {
            return JsonResult.build("该用户已经参加该抽奖,不允许重复参加");
        }
        //修改用户参与抽奖的数次
        user.setLotteryCount(userCount + 1);
        userMapper.updateByPrimaryKeySelective(user);
        //插入活动抽奖的用户参与信息
        LotActivityParticipants participants = new LotActivityParticipants();
        participants.setUserId(userId);
        participants.setActivityId(activityId);
        participants.setCreateTime(currentDate);
        participants.setFormId(reqJoinLottery.getFromId());
        participants.setOpenId(user.getOpenId());
        participants.setPrizeProvider(activity.getPrizeProvider());
        int i = activityParticipantsMapper.insertSelective(participants);
        if (1 != i) {
            throw new BusinessException("插入抽奖用户信息失败");
        }

        //更新活动信息
        Byte ruleType = activity.getRuleType();
        Integer joinNum = activity.getJoinNum();
        Integer setNum = activity.getSetNum();
        LotActivityExample afterActivityExample = new LotActivityExample();
        afterActivityExample.createCriteria().andIdEqualTo(activityId).andJoinNumEqualTo(joinNum);
        activity.setJoinNum(joinNum + 1);
        int j = activityMapper.updateByExampleSelective(activity, afterActivityExample);
        if (1 != j) {
            throw new BusinessException("修改抽奖活动信息失败");
        }

        //当开奖规则为到达指定人数后,在业务执行完成后执行开奖
        if (2 == ruleType) {
            //当达到参与人数时
            if (joinNum == setNum - 1) {
                DrawVo drawVo = new DrawVo();
                drawVo.setActivityId(activityId);
                drawVo.setUserId(activity.getCreateById());
                draw(drawVo);
            }
        }
        return JsonResult.ok();
    }

    /**
     * @param lotActivity 活动实体
     * @author XOu
     * @description 活动开奖前期交验
     * @version 1.0
     * @date 2018/6/18
     * @modified
     */
    private JsonResult preCheckout(LotActivity lotActivity, LotUser lotUser) {
        if (null == lotActivity) {
            log.error("==========活动不存在");
            return JsonResult.build("活动不存在");
        }
        if (1 != lotActivity.getPutStatus()) {
            log.error("==========活动未上架");
            return JsonResult.build("活动未上架");
        }
        if (1 != lotActivity.getStatus()) {
            log.error("==========活动状态异常");
            return JsonResult.build("活动状态异常");
        }
        if (null == lotUser || !lotActivity.getCreateById().equals(lotUser.getId())) {
            log.error("==========开奖请求的用户信息不存在,或者并不是本次活动的发起者,不能进行开奖");
            return JsonResult.build("你不是本次活动的发起者不能进行开奖");
        }
        Date endTime = lotActivity.getEndTime();
        if (null != endTime && endTime.before(new Date())) {
            //设置了活动结束时间,且当前时间已经超过结束时间,把活动置为失效
            updateActivityExp(lotActivity);
            log.error("==========对不起活动已经超过有效期");
            return JsonResult.build("对不起活动已经超过有效期");
        }
        Byte ruleType = lotActivity.getRuleType();
        if (1 > lotActivity.getJoinNum()) {
            log.error("==========参与抽检人数小于1人,开奖失败");
            //当是自动开奖和人数到达指定后开奖时当人数不足1人则失效
            if (3 != ruleType) {
                //自动开奖时,当参与人数小于1,则本次活动失效
                updateActivityExp(lotActivity);
            }
            return JsonResult.build("参与抽检人数小于1人,开奖失败");
        }

        return JsonResult.ok();
    }

    /**
     * @param list    中奖名单
     * @param prizeId 中奖奖品id
     * @param type    奖品类型 1:实物, 2:优惠券
     * @author XOu
     * @description 更新中奖
     * @version 1.0
     * @date 2018/6/19
     * @modified
     */
    private void updateByWon(List<LotActivityParticipants> list, Long prizeId, int type) {
        if (2 == type) {
            IdWorker idWorker = IdWorker.getInstance();
            long key;
            for (LotActivityParticipants participants : list) {
                key = idWorker.nextId();
                participants.setCouponKey(String.valueOf(key));
            }
        }
        Map<String, Object> param = new HashMap<>();
        param.put("list", list);
        param.put("prizeId", prizeId);
        param.put("isWon", 1);
        //更新中奖
        activityParticipantsMapper.updateByWon(param);
        //更新用户中奖次数
        userMapper.updateWonCount(param);
    }

    /**
     * @param list 未中奖名单
     * @author XOu
     * @description 更新未中奖名单
     * @version 1.0
     * @date 2018/6/19
     * @modified
     */
    private void updateByNotWon(List<LotActivityParticipants> list) {
        Map<String, Object> param = new HashMap<>();
        param.put("list", list);
        param.put("isWon", 0);
        activityParticipantsMapper.updateByWon(param);
    }

    /**
     * @param lotActivity 活动对象
     * @author XOu
     * @description 更新活动失效
     * @version 1.0
     * @date 2018/6/22
     * @modified
     */
    private void updateActivityExp(LotActivity lotActivity) {
        lotActivity.setStatus((byte) 3);
        lotActivity.setEndTime(new Date());
        activityMapper.updateByPrimaryKeySelective(lotActivity);
        LotActivityParticipants activityParticipants = new LotActivityParticipants();
        activityParticipants.setIsWon((byte) 3);
        LotActivityParticipantsExample participantsExample = new LotActivityParticipantsExample();
        participantsExample.createCriteria().andActivityIdEqualTo(lotActivity.getId());
        activityParticipantsMapper.updateByExampleSelective(activityParticipants, participantsExample);
    }


}
